package org.orbis.memorymanager.filter;

import java.io.IOException;
import java.util.ArrayList;
import org.orbis.communicate.Configuration;
import org.orbis.communicate.deleter.DeleterPackage;
import org.orbis.constants.Constants;
import org.orbis.logging.DeleterLog;
import org.orbis.structure.BlockingIntegerList;
import org.orbis.structure.BlockingLongList;

public final class DeleteFilter{
	private ArrayList<String> deletedContent;
	private int contentIndex;
	private ArrayList<String> deletedAppendix;
	private int appendixIndex;
	private BlockingLongList deletedID;
	private BlockingIntegerList[] deletedIntFlag;
	private BlockingLongList[] deletedLongFlag;
	private DeleterLog deleterLogger;

	public DeleteFilter(Configuration conf) throws IOException{
		this.deletedContent = new ArrayList<String>();
		this.contentIndex = conf.contentDeleteType();
		this.deletedAppendix = new ArrayList<String>();
		this.appendixIndex = conf.appendixDeleteType();
		this.deletedID = new BlockingLongList();
		this.deletedIntFlag = new BlockingIntegerList[conf.contentInfo().integerFlagNum()];
		for(int i = 0; i < this.deletedIntFlag.length; i++){
			this.deletedIntFlag[i] = new BlockingIntegerList();
		}
		this.deletedLongFlag = new BlockingLongList[conf.contentInfo().longFlagNum()];
		for(int i = 0; i < this.deletedLongFlag.length; i++){
			this.deletedLongFlag[i] = new BlockingLongList();
		}
		this.deleterLogger = new DeleterLog(conf.logDirectory(), "DeleterLog.log");

		if(this.deleterLogger.isReliefMode()) backup();
	}

	private void addContent(String content){
		deletedContent.add(content);
	}

	private void addAppendix(String appendix){
		deletedAppendix.add(appendix);
	}

	private void addID(long ID){
		deletedID.add(ID);
	}

	private void addIntFlag(int type, int flag){
		deletedIntFlag[type].add(flag);
	}

	private void addLongFlag(int type, long flag){
		deletedLongFlag[type].add(flag);
	}

	// Obtain lasted data when system stopped unsuccessfully
	private void backup() throws IOException{
		while(!deleterLogger.isEndToRead()){
			int type = deleterLogger.getNextType();
			switch(type){
			case Constants.DELETE_TYPE_CONTENT:
				addContent(deleterLogger.reliefString());
				break;
			case Constants.DELETE_TYPE_APPENDIX:
				addAppendix(deleterLogger.reliefString());
				break;
			case Constants.DELETE_TYPE_ID:
				addID(deleterLogger.reliefLong());
				break;
			case Constants.DELETE_TYPE_LONGFLAG:
				addLongFlag(deleterLogger.reliefFlagType(), deleterLogger.reliefLong());
				break;
			case Constants.DELETE_TYPE_INTFLAG:
				addIntFlag(deleterLogger.reliefFlagType(), deleterLogger.reliefInt());
				break;
			default:
			}
		}

		deleterLogger.endRelief();
	}

	public void deleteFile(){
		try{
			deleterLogger.terminate();
		}catch(IOException e){
			e.printStackTrace();
		}
	}

	public void add(DeleterPackage pkg){
		try{
			switch(pkg.type()){
			case Constants.DELETE_TYPE_ID:
				deleterLogger.logID(pkg.ID());
				addID(pkg.ID());
				break;
			case Constants.DELETE_TYPE_CONTENT:
				deleterLogger.logContent(pkg.strval());
				addContent(pkg.strval());
				break;
			case Constants.DELETE_TYPE_APPENDIX:
				deleterLogger.logAppendix(pkg.strval());
				addAppendix(pkg.strval());
				break;
			case Configuration.DELTYPE_INTFLAG:
				deleterLogger.logIntFlag(pkg.flagType(), pkg.intFlag());
				addIntFlag(pkg.flagType(), pkg.intFlag());
				break;
			case Configuration.DELTYPE_LONGFLAG:
				deleterLogger.logLongFlag(pkg.flagType(), pkg.longFlag());
				addLongFlag(pkg.flagType(), pkg.longFlag());
				break;
			}
		}catch(IOException e){
			e.printStackTrace();
		}
	}

	public int contentIndex(){
		return contentIndex;
	}

	public boolean filterContent(String content){
		return deletedContent.contains(content);
	}

	public int appendixIndex(){
		return appendixIndex;
	}

	public boolean filterAppendix(String appendix){
		return deletedAppendix.contains(appendix);
	}

	public boolean filterID(long ID){
		return deletedID.contains(ID);
	}

	public boolean filterIntFlag(int type, int value){
		return deletedIntFlag[type].contains(value);
	}

	public boolean filterLongFlag(int type, long value){
		return deletedLongFlag[type].contains(value);
	}

	public void removeContent(String content){
		int index = deletedContent.indexOf(content);
		if(index != -1) deletedContent.remove(index);
	}

	public void removeAppendix(String appendix){
		int index = deletedAppendix.indexOf(appendix);
		if(index != -1) deletedAppendix.remove(index);
	}

	public void removeID(long ID){
		int index = deletedID.indexOf(ID);
		if(index != -1) deletedID.removeByIndex(index);
	}

	public void removeIntFlag(int type, int flag){
		int index = deletedIntFlag[type].indexOf(flag);
		if(index != -1) deletedIntFlag[type].removeByIndex(index);
	}

	public void removeLongFlag(int type, long flag){
		int index = deletedLongFlag[type].indexOf(flag);
		if(index != -1) deletedLongFlag[type].removeByIndex(index);
	}

	public int filterCount(){
		int size = deletedContent.size() + deletedAppendix.size() + deletedID.size();
		for(int i = 0; i < deletedIntFlag.length; i++)
			size += deletedIntFlag[i].size();
		for(int i = 0; i < deletedLongFlag.length; i++)
			size += deletedLongFlag[i].size();

		return size;
	}

	public void terminate() throws IOException{
		deleterLogger.terminate();
	}

	@Override
	protected void finalize() throws Throwable{
		deleterLogger.terminate();
	}
}
